package spring.context;

import spring.beans.ImportBeanDefinitionRegistrar;
import spring.beans.config.BeanDefinition;
import spring.beans.factory.DefaultListableBeanFactory;
import spring.beans.BeanPostProcessor;
import spring.core.Ordered;
import spring.core.PriorityOrdered;

import java.util.ArrayList;
import java.util.List;

/**
 * 委托执行post processors任务的工具类
 */
public class PostProcessorRegistrationDelegate {

    /**
     * 注册BeanPostProcessor
     * @param registry
     */
    public static void registerBeanPostProcessors(DefaultListableBeanFactory registry) {

        // 找到所有注册到容器的 BeanPostProcessor 的名字
        ArrayList<String> postProcessorNames = registry.getBeanNamesForType(BeanPostProcessor.class);

        // 将 BeanPostProcessor 分成三类处理 : PriorityOrdered, Ordered 和 其它
        List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<BeanPostProcessor> orderedPostProcessorNames = new ArrayList<>();
        List<BeanPostProcessor> nonOrderedPostProcessorNames = new ArrayList<>();
        for (String postProcessorName : postProcessorNames) {
            BeanDefinition beanDefinition = registry.getBeanDefinition(postProcessorName);
            Class clazz = beanDefinition.getClazz();
            // 这里了getBean
            BeanPostProcessor pp = registry.getBean(postProcessorName, BeanPostProcessor.class);
            if (PriorityOrdered.class.isAssignableFrom(clazz)) {
                priorityOrderedPostProcessors.add(pp);
            } else if (Ordered.class.isAssignableFrom(clazz)) {
                orderedPostProcessorNames.add(pp);
            } else {
                nonOrderedPostProcessorNames.add(pp);
            }
        }
        for (BeanPostProcessor postProcessor : priorityOrderedPostProcessors) {
            registry.addBeanPostProcessor(postProcessor);
        }
        for (BeanPostProcessor postProcessor : orderedPostProcessorNames) {
            registry.addBeanPostProcessor(postProcessor);
        }
        for (BeanPostProcessor postProcessor : nonOrderedPostProcessorNames) {
            registry.addBeanPostProcessor(postProcessor);
        }

    }

    /**
     * 注册spring内部一些其他的单例
     * 方法逻辑是自己写的，主要是回调ImportBeanDefinitionRegistrar接口的方法
     */
    public static void invokeBeanFactoryPostProcessors(DefaultListableBeanFactory beanFactory) {
        ArrayList<String> beanDefinitionRegistrarsNames = beanFactory.getBeanNamesForType(ImportBeanDefinitionRegistrar.class);

        for (String name : beanDefinitionRegistrarsNames){
            ImportBeanDefinitionRegistrar bean = beanFactory.getBean(name, ImportBeanDefinitionRegistrar.class);
            bean.registerBeanDefinitions(beanFactory);
        }

    }
}
